package com.lxh.cp.config;

import com.google.common.collect.Maps;
import com.lxh.cp.handler.*;
import lombok.val;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.config.WxCpConfigStorage;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import me.chanjar.weixin.cp.config.impl.WxCpRedisConfigImpl;
import me.chanjar.weixin.cp.constant.WxCpConsts;
import me.chanjar.weixin.cp.message.WxCpMessageRouter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * created by lanxinghua@2dfire.com on 2020/2/23
 */
@Configuration
@EnableConfigurationProperties(WxCpProperties.class)
public class WxCpConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(WxCpConfiguration.class);

    private static Map<Integer/*agentId*/, WxCpMessageRouter> routers = Maps.newHashMap();
    private static Map<Integer/*agentId*/, WxCpService> cpServices = Maps.newHashMap();

    private WxCpProperties properties;

    // 更新2020.2.25 加入redis
    @Resource
    private JedisPool jedisPool;

    private LogHandler logHandler;
    private NullHandler nullHandler;
    private ScanHandler scanHandler;
    private LocationHandler locationHandler;
    private MenuHandler menuHandler;
    private MsgHandler msgHandler;
    private UnsubscribeHandler unsubscribeHandler;
    private SubscribeHandler subscribeHandler;

    @Autowired
    public WxCpConfiguration(LogHandler logHandler, NullHandler nullHandler, LocationHandler locationHandler,
                             MenuHandler menuHandler, MsgHandler msgHandler, UnsubscribeHandler unsubscribeHandler,
                             SubscribeHandler subscribeHandler, WxCpProperties properties) {
        this.logHandler = logHandler;
        this.nullHandler = nullHandler;
        this.locationHandler = locationHandler;
        this.menuHandler = menuHandler;
        this.msgHandler = msgHandler;
        this.unsubscribeHandler = unsubscribeHandler;
        this.subscribeHandler = subscribeHandler;
        this.properties = properties;
    }

    public static Map<Integer, WxCpMessageRouter> getRouters() {
        return routers;
    }

    public static WxCpMessageRouter getRouter(Integer agentId) {
        return routers.get(agentId);
    }

    public static WxCpService getCpService(Integer agentId) {
        return cpServices.get(agentId);
    }


    /**
     * 初始化服务
     */
    @PostConstruct
    public void initServices() {
        // 默认缓存在内存中，配置redis就放入redis中
        cpServices = this.properties.getConfigs().stream().map(a -> {
            if (redisIsOk()){
                val configStorage = new WxCpRedisConfigImpl(jedisPool);
                configStorage.setCorpId(this.properties.getCorpId());
                configStorage.setAgentId(a.getAgentId());
                configStorage.setCorpSecret(a.getSecret());
                configStorage.setToken(a.getToken());
                configStorage.setAesKey(a.getAesKey());
                val service = new WxCpServiceImpl();
                service.setWxCpConfigStorage(configStorage);
                routers.put(a.getAgentId(), this.newRouter(service));
                return service;
            }else {
                val configStorage = new WxCpDefaultConfigImpl();
                configStorage.setAgentId(a.getAgentId());
                configStorage.setCorpId(this.properties.getCorpId());
                configStorage.setToken(a.getToken());
                configStorage.setCorpSecret(a.getSecret());
                configStorage.setAesKey(a.getAesKey());
                val service = new WxCpServiceImpl();
                service.setWxCpConfigStorage(configStorage);
                routers.put(a.getAgentId(), this.newRouter(service));
                return service;
            }
        }).collect(Collectors.toMap(service -> service.getWxCpConfigStorage().getAgentId(), a -> a));
    }


    /**
     * redis是否可用
     * @return
     */
    private boolean redisIsOk(){
        try {
            Jedis jedis = jedisPool.getResource();
            jedis.ping();
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 消息路由处理
     * @param wxCpService
     * @return
     */
    private WxCpMessageRouter newRouter(WxCpService wxCpService) {
        final val newRouter = new WxCpMessageRouter(wxCpService);

        // 记录所有事件的日志 （异步执行）
        newRouter.rule().handler(this.logHandler).next();
        // 自定义菜单事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.MenuButtonType.CLICK).handler(this.menuHandler).end();
        // 点击菜单链接事件（这里使用了一个空的处理器，可以根据自己需要进行扩展）
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.MenuButtonType.VIEW).handler(this.nullHandler).end();
        // 关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.SUBSCRIBE).handler(this.subscribeHandler)
                .end();
        // 取消关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.UNSUBSCRIBE)
                .handler(this.unsubscribeHandler).end();
        // 上报地理位置事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.LOCATION).handler(this.locationHandler)
                .end();
        // 接收地理位置消息
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.LOCATION)
                .handler(this.locationHandler).end();
        // 扫码事件（这里使用了一个空的处理器，可以根据自己需要进行扩展）
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxConsts.EventType.SCAN).handler(this.scanHandler).end();
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxCpConsts.EventType.CHANGE_CONTACT).handler(new ContactChangeHandler()).end();
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
                .event(WxCpConsts.EventType.ENTER_AGENT).handler(new EnterAgentHandler()).end();

        // 默认
        newRouter.rule().async(false).handler(this.msgHandler).end();
        return newRouter;
    }
}
